home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / vim_src.zip / TERM.C < prev    next >
C/C++ Source or Header  |  1993-01-12  |  17KB  |  763 lines

  1. /* vi:sw=4:ts=4:
  2.  *
  3.  * term.c -- VIM - Vi IMitation
  4.  *
  5.  * primitive termcap support added
  6.  *
  7.  * NOTE: padding and variable substitution is not performed,
  8.  * when compiling without TERMCAP, we use tputs() and tgoto() dummies.
  9.  *
  10.  * 14.6.92
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #include "param.h"
  16. #include "proto.h"
  17. #ifdef TERMCAP
  18. # ifdef linux
  19. #  include <termcap.h>
  20. #  define TPUTSFUNCAST (outfuntype)
  21. # else
  22. #  define TPUTSFUNCAST
  23. #  ifdef AMIGA
  24. #   include "proto/termlib.pro"
  25. #  endif
  26. # endif
  27. #endif
  28.  
  29. /* buffer size for termcap entry */
  30. #ifdef linux
  31. # define TBUFSZ 2048
  32. #else
  33. # define TBUFSZ 1024
  34. #endif
  35.  
  36. #ifdef DEBUG
  37. # define TTEST(a) debug1("%s: ", "a"); if (a) {debug2("%02x %s\n", *a, a + 1);} else debug("NULL\n");
  38. #endif
  39.  
  40. static void parse_builtin_tcap __ARGS((Tcarr *tc, char *s));
  41.  
  42. /*
  43.  * Builtin_tcaps must always contain DFLT_TCAP as the first entry!
  44.  * DFLT_TCAP is used, when no terminal is specified with -T option or $TERM.
  45.  * The entries are compact, therefore they normally are included even when
  46.  * TERMCAP is defined.
  47.  * When TERMCAP is defined, the builtin entries can be accessed with
  48.  * "builtin_amiga", "builtin_ansi", "builtin_debug", etc.
  49.  */
  50. static char *builtin_tcaps[] =
  51. {
  52. #ifndef NO_BUILTIN_TCAPS
  53.   DFLT_TCAP,        /* almost allways included */
  54. # if !defined(UNIX) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  55.   ANSI_TCAP,        /* default for unix */
  56. # endif
  57. # if !defined(AMIGA) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  58.   AMIGA_TCAP,        /* default for amiga */
  59. # endif
  60. # if !defined(MSDOS) && (defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS))
  61.   PCTERM_TCAP,        /* default for MSdos */
  62. # endif
  63. # if !defined(ATARI) && defined(ALL_BUILTIN_TCAPS)
  64.   ATARI_TCAP,        /* default for Atari */
  65. # endif
  66. # if defined(UNIX) || defined(ALL_BUILTIN_TCAPS) || defined(SOME_BUILTIN_TCAPS)
  67.   XTERM_TCAP,        /* always included on unix */
  68. # endif
  69. # ifdef ALL_BUILTIN_TCAPS
  70.   VT52_TCAP,
  71. # endif
  72. # if defined(DEBUG) || defined(ALL_BUILTIN_TCAPS)
  73.   DEBUG_TCAP,        /* always included when debugging */
  74. # endif
  75. #else /* NO_BUILTIN_TCAPS */
  76.   "dump\0\0\0",
  77. #endif /* NO_BUILTIN_TCAPS */
  78.   NULL,
  79. };
  80.  
  81. /*
  82.  * Term_strings contains currently used terminal strings.
  83.  * It is initialized with the default values by parse_builtin_tcap().
  84.  * The values can be changed by setting the parameter with the same name.
  85.  */
  86. Tcarr term_strings;
  87.  
  88. /*
  89.  * Parsing of the builtin termcap entries.
  90.  * The terminal's name is not set, as this is already done in termcapinit().
  91.  * Chop builtin termcaps, string entries are already '\0' terminated.
  92.  * not yet implemented:
  93.  *   boolean entries could be empty strings;
  94.  *   numeric entries would need a flag (e.g. high bit of the skip byte),
  95.  *   so that parse_builtin_tcap can handle them.
  96.  */
  97.     static void
  98. parse_builtin_tcap(tc, s)
  99.     Tcarr *tc;
  100.     char *s;
  101. {
  102.     char **p = &tc->t_name;
  103.  
  104.     p++;
  105.     for (;;)
  106.     {
  107.         while (*s++)
  108.             ;
  109.         p += *s++;
  110.         if (!*s)
  111.             return;
  112.         *p++ = s;
  113.     }
  114. }
  115.  
  116. #ifdef TERMCAP
  117. # ifndef linux        /* included in <termlib.h> */
  118. #  ifndef AMIGA        /* included in proto/termlib.pro */
  119. int                tgetent();
  120. int                tgetnum();
  121. char            *tgetstr();
  122. int                tputs();
  123. #  endif /* AMIGA */
  124. extern short    ospeed;
  125. # endif /* linux */
  126. extern char        *UP, *BC, PC;
  127. #endif /* TERMCAP */
  128.  
  129.     void
  130. set_term(term)
  131.     char *term;
  132. {
  133.   char **p = builtin_tcaps;
  134. #ifdef TERMCAP
  135.   int builtin = 0;
  136. #endif
  137.   int width = 0, height = 0;
  138.  
  139.   clear_termparam();        /* clear old parameters */
  140.   if (!strncmp(term, "builtin_", (size_t)8))
  141.   {
  142.       term += 8;
  143. #ifdef TERMCAP
  144.       builtin = 1;
  145. #endif
  146.   }
  147. #ifdef TERMCAP
  148.   else
  149.   {
  150.       for (;;)
  151.       {
  152.           char            *p;
  153.           static char    tstrbuf[TBUFSZ];
  154.           char            tbuf[TBUFSZ];
  155.           char            *tp = tstrbuf;
  156.           int            i;
  157.  
  158.           i = tgetent(tbuf, term);
  159.           if (i == -1)
  160.           {
  161.             emsg("Cannot open termcap file");
  162.             builtin = 1;
  163.             break;
  164.           }
  165.           if (i == 0)
  166.           {
  167.             emsg("terminal entry not found");
  168.             builtin = 1;
  169.             break;
  170.           }
  171.  
  172.         /* output strings */
  173.           T_EL = tgetstr("ce", &tp);
  174.           T_IL = tgetstr("al", &tp);
  175.           T_CIL = tgetstr("AL", &tp);
  176.           T_DL = tgetstr("dl", &tp);
  177.           T_CDL = tgetstr("DL", &tp);
  178.           T_ED = tgetstr("cl", &tp);
  179.           T_CI = tgetstr("vi", &tp);
  180.           T_CV = tgetstr("ve", &tp);
  181.           T_TP = tgetstr("me", &tp);
  182.           T_TI = tgetstr("mr", &tp);
  183.           T_CM = tgetstr("cm", &tp);
  184.           T_SR = tgetstr("sr", &tp);
  185.           T_CRI = tgetstr("RI", &tp);
  186.           T_VB = tgetstr("vb", &tp);
  187.           T_KS = tgetstr("ks", &tp);
  188.           T_KE = tgetstr("ke", &tp);
  189.  
  190.         /* key codes */
  191.           term_strings.t_ku = tgetstr("ku", &tp);
  192.           term_strings.t_kd = tgetstr("kd", &tp);
  193.           term_strings.t_kl = tgetstr("kl", &tp);
  194.           term_strings.t_kr = tgetstr("kr", &tp);
  195.           /* term_strings.t_sku = tgetstr("", &tp); termcap code unknown */
  196.           /* term_strings.t_skd = tgetstr("", &tp); termcap code unknown */
  197.           term_strings.t_sku = NULL;
  198.           term_strings.t_skd = NULL;
  199.           term_strings.t_skl = tgetstr("#4", &tp);
  200.           term_strings.t_skr = tgetstr("%i", &tp);
  201.           term_strings.t_f1 = tgetstr("k1", &tp);
  202.           term_strings.t_f2 = tgetstr("k2", &tp);
  203.           term_strings.t_f3 = tgetstr("k3", &tp);
  204.           term_strings.t_f4 = tgetstr("k4", &tp);
  205.           term_strings.t_f5 = tgetstr("k5", &tp);
  206.           term_strings.t_f6 = tgetstr("k6", &tp);
  207.           term_strings.t_f7 = tgetstr("k7", &tp);
  208.           term_strings.t_f8 = tgetstr("k8", &tp);
  209.           term_strings.t_f9 = tgetstr("k9", &tp);
  210.           term_strings.t_f10 = tgetstr("k;", &tp);
  211.           term_strings.t_sf1 = tgetstr("F1", &tp);    /* really function keys 11-20 */
  212.           term_strings.t_sf2 = tgetstr("F2", &tp);
  213.           term_strings.t_sf3 = tgetstr("F3", &tp);
  214.           term_strings.t_sf4 = tgetstr("F4", &tp);
  215.           term_strings.t_sf5 = tgetstr("F5", &tp);
  216.           term_strings.t_sf6 = tgetstr("F6", &tp);
  217.           term_strings.t_sf7 = tgetstr("F7", &tp);
  218.           term_strings.t_sf8 = tgetstr("F8", &tp);
  219.           term_strings.t_sf9 = tgetstr("F9", &tp);
  220.           term_strings.t_sf10 = tgetstr("FA", &tp);
  221.           term_strings.t_help = tgetstr("%1", &tp);
  222.           term_strings.t_undo = tgetstr("&8", &tp);
  223.  
  224.           height = tgetnum("li");
  225.           width = tgetnum("co");
  226.  
  227.           BC = tgetstr("bc", &tp);
  228.           UP = tgetstr("up", &tp);
  229.           p = tgetstr("pc", &tp);
  230.           if (p)
  231.             PC = *p;
  232.           ospeed = 0;
  233.           break;
  234.         }
  235.     }
  236.   if (builtin)
  237. #endif
  238.     {
  239.       while (*p && strcmp(term, *p))
  240.         p++;
  241.       if (!*p)
  242.         {
  243.           fprintf(stderr, "'%s' not builtin. Available terminals are:\n", term);
  244.           for (p = builtin_tcaps; *p; p++)
  245.             fprintf(stderr, "\t%s\n", *p);
  246.           sleep(2);
  247.           fprintf(stderr, "defaulting to '%s'\n", *builtin_tcaps);
  248.           sleep(2);
  249.           p = builtin_tcaps;
  250.           if (term_strings.t_name)
  251.             free(term_strings.t_name);
  252.           term_strings.t_name = strsave(term = *p);
  253.         }
  254.       parse_builtin_tcap(&term_strings, *p);
  255.     }
  256. #if defined(AMIGA) || defined(MSDOS)
  257.   /* DFLT_TCAP indicates that it is the machine console. */
  258.   if (strcmp(term, *builtin_tcaps))
  259.       term_console = FALSE;
  260.   else
  261.       term_console = TRUE;
  262. #endif
  263.    ttest(TRUE);
  264.   /* display initial screen after ttest() checking. jw. */
  265.   if (width <= 0 || height <= 0)
  266.     {
  267.       /* termcap failed to report size */
  268.       /* set defaults, in case mch_get_winsize also fails */
  269.       width = 80;
  270.       height = 24;
  271.     }
  272.   set_winsize(width, height, FALSE);  
  273.  }
  274.  
  275. #ifndef TERMCAP
  276.  
  277. static char *titoa __PARMS((int));
  278.  
  279. /*
  280.  * minimal tgoto() implementation.
  281.  * no padding and we only parse for %i %d and %+char
  282.  */
  283.  
  284. static char *
  285. titoa(i)
  286.   int i;
  287. {
  288.   static char buf[10];
  289.   char *p;
  290.  
  291.   p = buf + 9;
  292.   *p = '\0';
  293.   do
  294.     {
  295.       --p;
  296.       *p = i % 10 + '0';
  297.       i /= 10;
  298.     }
  299.   while (i > 0 && p > buf);
  300.   return p;
  301. }
  302.  
  303. char *
  304. tgoto(cm, x, y)
  305. char *cm;
  306. int x, y;
  307. {
  308.   static char buf[30];
  309.   char *p, *s, *e;
  310.  
  311.   if (!cm)
  312.     return "OOPS";
  313.   e = buf + 29;
  314.   for (s = buf; s < e && *cm; cm++)
  315.     {
  316.       if (*cm != '%')
  317.         {
  318.       *s++ = *cm;
  319.       continue;
  320.     }
  321.       switch (*++cm)
  322.         {
  323.     case 'd':
  324.       p = titoa(y);
  325.       y = x;
  326.       while (*p)
  327.         *s++ = *p++;
  328.       break;
  329.     case 'i':
  330.       x++;
  331.       y++;
  332.       break;
  333.     case '+':
  334.       *s++ = (char)(*++cm + y);
  335.       y = x;
  336.       break;
  337.         case '%':
  338.       *s++ = *cm;
  339.       break;
  340.     default:
  341.           return "OOPS";
  342.     }
  343.     }
  344.   *s = '\0';
  345.   return buf;
  346. }
  347.  
  348. #endif /* TERMCAP */
  349.  
  350. /*
  351.  * termcapinit is called from main() to initialize the terminal
  352.  * the optional argument is given with the -T command line option
  353.  */
  354.     void
  355. termcapinit(term)
  356.     char *term;
  357. {
  358.     if (!term)
  359.         term = getenv("TERM");
  360.     if (!term || !*term)
  361.         term = *builtin_tcaps;
  362.     term_strings.t_name = strsave(term);
  363.     set_term(term);
  364. }
  365.  
  366. /*
  367.  * a never-padding outstr.
  368.  * use this whenever you don't want to run the string through tputs.
  369.  * tputs above is harmless, but tputs from the termcap library 
  370.  * is likely to strip off leading digits, that it mistakes for padding
  371.  * information. (jw)
  372.  */
  373.     void
  374. outstrn(s)
  375.     char *s;
  376. {
  377.     while (*s)
  378.         outchar(*s++);
  379. }
  380.  
  381. #ifndef MSDOS        /* there is a special version of outstr() in msdos.c */
  382. /*
  383.  * outstr(s): put a string character at a time into the output buffer.
  384.  * If TERMCAP is defined use the termcap parser. (jw)
  385.  */
  386.     void
  387. outstr(s)
  388.     register char             *s;
  389. {
  390.     if (s)
  391. #ifdef TERMCAP
  392.         tputs(s, 1, TPUTSFUNCAST outchar);
  393. #else
  394.         while (*s)
  395.             outchar(*s++);
  396. #endif
  397. }
  398. #endif /* MSDOS */
  399.  
  400. /* 
  401.  * cursor positioning using termcap parser. (jw)
  402.  */
  403.     void
  404. windgoto(row, col)
  405.     int        row;
  406.     int        col;
  407. {
  408. #ifdef TERMCAP
  409.     tputs(tgoto(T_CM, col, row), 1, TPUTSFUNCAST outchar);
  410. #else
  411.     outstr(tgoto(T_CM, col, row));
  412. #endif
  413. }
  414.  
  415. /*
  416.  * Set cursor to current position.
  417.  * Should be optimized for minimal terminal output.
  418.  */
  419.  
  420.     void
  421. setcursor()
  422. {
  423.     if (!RedrawingDisabled)
  424.         windgoto(Cursrow, Curscol);
  425. }
  426.  
  427.     void
  428. ttest(pairs)
  429.     int    pairs;
  430. {
  431.     char buf[70];
  432.     char *s = "terminal capability %s required.\n";
  433.     char *t = NULL;
  434.  
  435. #ifdef TTEST
  436.   TTEST(T_EL);
  437.   TTEST(T_IL);
  438.   TTEST(T_CIL);
  439.   TTEST(T_DL);
  440.   TTEST(T_CDL);
  441.   TTEST(T_ED);
  442.   TTEST(T_CI);
  443.   TTEST(T_CV);
  444.   TTEST(T_TP);
  445.   TTEST(T_TI);
  446.   TTEST(T_CM);
  447.   TTEST(T_SR);
  448.   TTEST(T_CRI);
  449. #endif /* TTEST */
  450.  
  451.   /* hard requirements */
  452.     if (!T_ED || !*T_ED)    /* erase display */
  453.         t = "cl";
  454.     if (!T_CM || !*T_CM)    /* cursor motion */
  455.         t = "cm";
  456.  
  457.     if (t)
  458.     {
  459.         sprintf(buf, s, t);
  460.         emsg(buf);
  461.     }
  462.  
  463.     if (pairs)
  464.     {
  465.       /* optional pairs */
  466.         if ((!T_TP || !*T_TP) ^ (!T_TI || !*T_TI))
  467.         {
  468.             debug2("cap :me=%s:mr=%s: ignored\n", T_TP, T_TI);
  469.             T_TP = T_TI = NULL;
  470.         }
  471.         if ((!T_CI || !*T_CI) ^ (!T_CV || !*T_CV))
  472.         {
  473.             debug2("cap :vi=%s:ve=%s: ignored\n", T_CI, T_CV);
  474.             T_CI = T_CV = NULL;
  475.         }
  476.     }
  477. }
  478.  
  479. /*
  480.  * inchar() - get a character from
  481.  *        1. a scriptfile
  482.  *        2. the keyboard - take care of interpreting escape sequences
  483.  *
  484.  *    If we got an interrupt all input is read until none is available.
  485.  *  If async is TRUE there is no waiting for the char and we keep the
  486.  *   character.
  487.  */
  488.  
  489. #define INBUFLEN 50        /* buffer lengt, must be enough to contain an
  490.                             Amiga raw keycode report */
  491.  
  492.     int
  493. inchar(async)
  494.     int async;
  495. {
  496.     static u_char    buf[INBUFLEN+1];    /* already entered characters */
  497.     static int        len = 0;            /* number of valid chars in buf */
  498.     static int        lastc = -1;            /* last character from script file */
  499.     register int     c;
  500.     register int     slen = 0;
  501.     register char     **p;
  502. #ifdef AMIGA
  503.              char    *s;
  504. #endif /* AMIGA */
  505.              int    first;
  506.              int    mode_deleted = FALSE;
  507.  
  508.     if (!async)
  509.         flushbuf();
  510.  
  511. /*
  512.  * Check for interrupt.
  513.  */
  514.     breakcheck();
  515.  
  516. /*
  517.  * first try script file
  518.  *    If interrupted: Stop reading script files.
  519.  */
  520. retry:
  521.     if (scriptin[curscript] != NULL)
  522.     {
  523.         if (!got_int && lastc >= 0)
  524.             c = lastc;
  525.         else if (got_int || (c = getc(scriptin[curscript])) < 0)    /* reached EOF */
  526.         {
  527.             lastc = -1;
  528.             fclose(scriptin[curscript]);
  529.             scriptin[curscript] = NULL;
  530.             if (curscript > 0)
  531.                 --curscript;
  532.                 /* recovery may be delayed till after reading a script file */
  533.             if (recoverymode)
  534.                 openrecover();
  535.             goto retry;        /* may read other script if this one was nested */
  536.         }
  537.         if (c == 0)
  538.             c = K_ZERO;        /* replace ^@ with special code */
  539.         if (async)
  540.             lastc = c;
  541.         else
  542.             lastc = -1;
  543.         return c;
  544.     }
  545.  
  546. /*
  547.  * If we got an interrupt, skip all previously typed characters and
  548.  * reset interrupt flag.
  549.  */
  550.     if (got_int)        /* skip typed characters */
  551.     {
  552.         while (GetChars((char *)buf, INBUFLEN, T_PEEK))
  553.             ;
  554.         got_int = FALSE;
  555.         len = 0;
  556.     }
  557. /*
  558.  * get character(s) from the keyboard
  559.  * this is repeated until we have found that
  560.  * - it is not an escape sequence, return the first char
  561.  * - it is the start of an escape sequence, but it is not completed within
  562.  *   a short time, return the first char
  563.  * - it is an escape seqence, translate it into a single byte code
  564.  */
  565.     first = TRUE;
  566.     for (;;)
  567.     {
  568.         if (!first || len == 0)
  569.         {
  570.             /*
  571.              * special case: if we get an <ESC> in insert mode and there are
  572.              * no more characters at once, we pretend to go out of insert mode.
  573.              * This prevents the one second delay after typing an <ESC>.
  574.              * If we get something after all, we may have to redisplay the
  575.              * mode. That the cursor is in the wrong place does not matter.
  576.              */
  577.             if (!async && len == 1 && buf[0] == ESC && (State == INSERT || State == REPLACE) && p_timeout)
  578.             {
  579.                 slen = GetChars((char *)buf + len, INBUFLEN - len, T_PEEK);
  580.                 if (slen != 0)
  581.                 {
  582.                     len += slen;
  583.                     goto gotchar;
  584.                 }
  585.                 if (p_mo)
  586.                 {
  587.                     delmode();
  588.                     mode_deleted = TRUE;
  589.                 }
  590.                 if (Curscol)        /* move cursor one left if possible */
  591.                     --Curscol;
  592.                 else if (Curpos.col != 0 && Cursrow)
  593.                 {
  594.                         --Cursrow;
  595.                         Curscol = Columns - 1;
  596.                 }
  597.                 setcursor();
  598.                 flushbuf();
  599.             }
  600.             /*
  601.              * When async == TRUE do not wait for characters to arrive: T_PEEK
  602.              * When getting the first character wait until one arrives: T_BLOCK
  603.              * When waiting for a key sequence to complete
  604.              *        and 'timeout' set wait a short time: T_WAIT
  605.              *        and 'timeout' not set wait until one arrives: T_BLOCK
  606.              */
  607.             slen = GetChars((char *)buf + len, INBUFLEN - len, async ? T_PEEK : (len == 0 || !p_timeout) ? T_BLOCK : T_WAIT);
  608.             len += slen;
  609.             if (async && len == 0)    /* was async and nothing typed */
  610.                 return NUL;
  611.             if (slen == 0)            /* escape sequence not completed in time */
  612.                 break;
  613.         }
  614.         first = FALSE;
  615.  
  616.         if (async)        /* when we get here: len != 0 */
  617.             return (int)buf[0];
  618.  
  619. gotchar:
  620.         /* search in the escape sequences for the characters we have */
  621.         for (p = (char **)&term_strings.t_ku; p != (char **)&term_strings.t_undo + 1; ++p)
  622.         {
  623.             if (*p == NULL)
  624.                 continue;
  625.             slen = strlen(*p);
  626.             if (strncmp(*p, (char *)buf, (size_t)(slen > len ? len : slen)) == 0)
  627.                 break;
  628.         }
  629.         if (p == (char **)&term_strings.t_undo + 1)    /* no match */
  630.         {
  631. #ifdef AMIGA        /* check for window bounds report */
  632.             buf[len] = 0;
  633.             if (buf[0] == CSI && ((s = strchr((char *)buf, 'r')) || (s = strchr((char *)buf, '|'))))
  634.             {
  635.                 slen = s - buf + 1;
  636.                 p = NULL;
  637.             }
  638.             else
  639. #endif
  640.                 break;
  641.         }
  642.         if (slen <= len)        /* got the complete sequence */
  643.         {
  644.             if (mode_deleted)
  645.                 showmode();
  646.             len -= slen;
  647.             memmove((char *)buf, (char *)buf + slen, (size_t)len);
  648. #ifdef AMIGA
  649.             if (p == NULL)        /* got window bounds report */
  650.             {
  651.                 set_winsize(0, 0, FALSE);      /* get size and redraw screen */
  652.                 continue;
  653.             }
  654. #endif
  655.  
  656.                 /* this relies on the Key numbers to be consecutive! */
  657.             return (int)(K_UARROW + (p - (char **)&term_strings.t_ku));
  658.         }
  659.         /*
  660.          * get here when we got an incomplete sequence,
  661.          * we need some more characters
  662.          */
  663.     }
  664.     c = buf[0];
  665.     memmove((char *)buf, (char *)buf+1, (size_t)--len);
  666.     if (c == 0)
  667.         c = K_ZERO;        /* replace ^@ with special code */
  668.         /* delete "INSERT" message if we return an ESC */
  669.     if (c == ESC && p_mo && !mode_deleted && (State == INSERT || State == REPLACE))
  670.         delmode();
  671.     return c;
  672. }
  673.  
  674. /*
  675.  * outnum - output a number fast (used for row and column numbers) (jw)
  676.  */
  677.     void
  678. outnum(n)
  679.     register int n;
  680. {
  681.     outstrn(tgoto("%d", 0, n));
  682. }
  683.  
  684.     void
  685. check_winsize()
  686. {
  687.     if (Columns < 5)
  688.         Columns = 5;
  689.     else if (Columns > MAX_COLUMNS)
  690.         Columns = MAX_COLUMNS;
  691.     if (Rows < 2)
  692.         Rows = 2;
  693.     p_scroll = Rows >> 1;
  694. }
  695.  
  696. /*
  697.  * set window size
  698.  * If 'mustset' is TRUE, we must set Rows and Columns, do not get real
  699.  * window size (this is used for the :win command during recovery).
  700.  * If 'mustset' is FALSE, we may try to get the real window size and if
  701.  * it fails use 'width' and 'height'.
  702.  */
  703.     void
  704. set_winsize(width, height, mustset)
  705.     int        width, height;
  706.     int        mustset;
  707. {
  708.     register int         tmp;
  709.  
  710.     if (width < 0 || height < 0)    /* just checking... */
  711.         return;
  712.  
  713.     if (State == HITRETURN)    /* postpone the resizing */
  714.     {
  715.         State = SETWINSIZE;
  716.         return;
  717.     }
  718.     screenclear();
  719. #ifdef AMIGA
  720.     flushbuf();         /* must do this before mch_get_winsize for some obscure reason */
  721. #endif /* AMIGA */
  722.     if (mustset || mch_get_winsize())
  723.     {
  724.         debug("mch_get_win failed\n");
  725.         Rows = height;
  726.         Columns = width;
  727.         mch_set_winsize();
  728.     }
  729.     check_winsize();        /* always check, to get p_scroll right */
  730.     if (State == HELP)
  731.             redrawhelp();
  732.     else
  733.     {
  734.             tmp = RedrawingDisabled;
  735.             RedrawingDisabled = FALSE;
  736.             updateScreen(CURSUPD);
  737.             RedrawingDisabled = tmp;
  738.             if (State == CMDLINE)
  739.                 redrawcmdline();
  740.             else
  741.                 setcursor();
  742.     }
  743.     flushbuf();
  744. }
  745.  
  746.     void
  747. settmode(raw)
  748.     int     raw;
  749. {
  750.     static int        oldraw = FALSE;
  751.  
  752.     if (oldraw == raw)        /* skip if already in desired mode */
  753.         return;
  754.     oldraw = raw;
  755.  
  756.     if (raw)
  757.         outstr(T_KS);    /* start "keypad transmit" mode */
  758.     else
  759.         outstr(T_KE);    /* stop "keypad transmit" mode */
  760.  
  761.     mch_settmode(raw);    /* machine specific function */
  762. }
  763.